using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Crainiate.Data.Persistence.Providers.Remoting
{
    [Serializable]
    public class RemoteCommand: Command, ISerializable
    {
        //Property values
        private RemoteManager _dispatcher; //Contains a remote reference to a dispatcher
        private RemoteContext _context;

        #region Interface

        //Constructors
        public RemoteCommand(RemoteContext context)
        {
            Context = context;
        }

        protected RemoteCommand(SerializationInfo info, StreamingContext context)
        {
            _context = info.GetValue("Context", typeof(RemoteContext)) as RemoteContext;
        }

        //Properties
        public virtual RemoteManager Dispatcher
        {
            get
            {
                return _dispatcher;
            }
            set
            {
                _dispatcher = value;
            }
        }

        public override Context Context
        {
            get
            {
                return _context;
            }
            set
            {
                if (value.GetType() != typeof(RemoteContext)) throw new RemotingProviderException("Context is not type RemoteContext.");
                _context = value as RemoteContext;
            }
        }

        //Load one record
        public override void Select(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            graph = _dispatcher.Select(graph, _context);
        }

        public override void Insert(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            graph = _dispatcher.Insert(graph, _context);
        }

        //Load many records
        public override void Execute(IQuery query) 
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            query = _dispatcher.Execute(query, _context);
        }

        public override void Update(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            graph = _dispatcher.Update(graph, _context);
        }

        public override void Delete(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            graph = _dispatcher.Delete(graph, _context);
        }

        //Exists one record
        public override bool Exists(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            return _dispatcher.Exists(graph, _context);
        }

        public override void Promote(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            graph = _dispatcher.Promote(graph, _context);
        }

        public override void Demote(IPersistable graph)
        {
            if (Dispatcher == null) throw new RemotingProviderException("Null Dispatcher. Command could not be performed. Set the Dispatcher property to perform a Command.");
            if (Context == null) throw new RemotingProviderException("Null Context. Command could not be performed. Set the Context property to a RemoteContext.");

            graph = _dispatcher.Demote(graph, _context);
        }

        public override void Reset()
        {
        }

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Context", _context);
        }

        #endregion
    }
}